import type { Spread } from './types-utils'

export const deepClone = <T>(target: T): T => JSON.parse(JSON.stringify(target))

/**
 * (bytes: number) => string
 * @description 字节换算
 * @param bytes 字节大小
 * @return 带单位带换算结果
 */
export const transBytes = (bytes: number) => {
  const UNIT = ['B', 'KB', 'MB', 'GB', 'TB']
  const MAX_THRESHOLD = Math.pow(1024, UNIT.length - 1)

  const formatter = (num: number, unit: string) => {
    const fixed_level = unit === UNIT[0] ? 0 : 2
    return num.toFixed(fixed_level) + ' ' + unit
  }

  const handler = (bytes: number, level = 0): string => {
    const threshold = Math.pow(1024, level)
    if (bytes >= MAX_THRESHOLD) return formatter(bytes / MAX_THRESHOLD, UNIT[UNIT.length - 1])
    if (bytes >= threshold * 1024) {
      return handler(bytes, level + 1)
    } else return formatter(bytes / threshold, UNIT[level])
  }

  if (!bytes) return formatter(0, UNIT[0])

  return handler(bytes)
}

/**
 * @description 时间转换
 * @param timestamp: number 
 * @param level: 1: YY-MM-DD HH:mm | 2: YY-MM-DD | 3: YY-MM-DD HH:mm:ss
 */
export const transDate = (timestamp: number, level = 1, connector = '-') => {
  const isMillisecond = (timestamp: any) => timestamp.toString().length === 13
  const sliceLastTowChar = (str: string) => str.slice(str.length - 2)

  if (!isMillisecond(timestamp)) timestamp = timestamp * 1000

  const d = new Date(timestamp)
  const year = d.getFullYear()
  const month = sliceLastTowChar(`0${d.getMonth() + 1}`)
  const date = sliceLastTowChar(`0${d.getDate()}`)
  const hours = sliceLastTowChar(`0${d.getHours()}`)
  const minutes = sliceLastTowChar(`0${d.getMinutes()}`)
  const seconds = sliceLastTowChar(`0${d.getSeconds()}`)

  if (level === 2) return year + connector + month + connector + date

  if (level === 3) {
    return year + connector + month + connector + date + ' '
      + hours + ':' + minutes + ':' + seconds
  }

  return year + connector + month + connector + date + ' ' + hours + ':' + minutes
}

/**
 * @description 异步等待
 * @param duration: 时长
 */
export const sleep = (duration: number) => {
  return new Promise(resovle => {
    setTimeout(() => {
      resovle('')
    }, duration)
  })
}

/**
 * @description Object.create 类型封装
 */
export const genObjectBy = <T extends object | null, V>(target: T, propsObject?: V): Spread<T & V> => {
  if (propsObject) return Object.assign(Object.create(target), propsObject)
  return Object.create(target)
}

/**
 * @description 将 x 秒格式化成 mm:ss
 * @param time: 秒级时间搓
 */
export const formatSeconds = (time: number) => {
  if (time < 1) {
    return '00:00';
  }
  let minute, second;
  minute = Math.floor(time / 60) + '';
  second = Math.floor(time % 60) + '';
  minute = minute.length === 1 ? '0' + minute : minute;
  second = second.length === 1 ? '0' + second : second;
  return minute + ':' + second;
};

/**
 * @description 获取指定的Cookie字段
 * @param name: 字段名称
 */
export const getCookieValue = (name: string) => {
  const cookies = document.cookie.split('; ');
  const cookie = cookies.find(cookie => cookie.startsWith(name));
  if (cookie) {
    return cookie.split('=')[1];
  }
  return null;
}

/**
 * @description 删除指定 cookie
 * @param name: 字段名称
 */
export const delCookie = (name: string) => {
  document.cookie = name + '=; domain=.zego.im; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; samesite=Lax';
}

/**
 * @description base64转File
 * @param urlData: base64字符串
 * @param fileName: 文件名
 */
export const base64ToFile = (urlData: string, fileName: string) => {
  const arr = urlData.split(',');
  const mime = (arr[0].match(/:(.*?);/) as any)[1];
  const suffix = mime.split('/')[1]
  const bytes = atob(arr[1]);
  let n = bytes.length
  const ia = new Uint8Array(n);
  while (n--) {
    ia[n] = bytes.charCodeAt(n);
  }
  return new File([ia], `${fileName}.${suffix}`, { type: mime });
}


/**
 * @description 获取视频详细信息
 * @param file: 文件File
 */
export const getMediaInfo = (file: File): Promise<number> => {
  return new Promise((resolve, reject) => {
    // @ts-ignore
    // eslint-disable-next-line no-undef
    MediaInfo(
      { format: 'object' },
      async (mediainfo: any) => {
        const getSize = () => file.size;
        const readChunk = (chunkSize: any, offset: any) =>
          new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onload = event => {
              if (event.target) {
                if (event.target.error) {
                  reject(event.target.error);
                }
                resolve(new Uint8Array(event.target.result as ArrayBufferLike));
              }
            };
            reader.readAsArrayBuffer(file.slice(offset, offset + chunkSize));
          });

        const { media: { track } } = await mediainfo.analyzeData(getSize, readChunk)

        const generalInfo = track.find((item: any) => item['@type'] === 'General');
        resolve(generalInfo.Duration || 0)
      }
    )
  })
}
/**
 * 
 * @description 时间戳时分秒转换
 * @returns 
 */
export function formatTime(timestamp: number) {
  let hours: number | string = Math.floor(timestamp / 3600);
  let minutes: number | string = Math.floor((timestamp - (hours * 3600)) / 60);
  let seconds: number | string = Math.floor(timestamp % 60);
  if (hours < 10) {
    hours = '0' + hours;
  }
  if (minutes < 10) {
    minutes = '0' + minutes;
  }
  if (seconds < 10) {
    seconds = '0' + seconds;
  }
  return hours + ':' + minutes + ':' + seconds;
}

/**
 * 
 * @description 秒转时分秒
 * @returns 
 */
export function formatSecond(value: number): string {
  let theTime = Math.floor(value); // 秒
  let theTime1 = 0; // 分
  let theTime2 = 0; // 小时
  if (theTime > 60) {
    theTime1 = Math.floor(theTime / 60);
    theTime = Math.floor(theTime % 60);
    if (theTime1 > 60) {
      theTime2 = Math.floor(theTime1 / 60);
      theTime1 = Math.floor(theTime1 % 60);
    }
  }
  let result = '' + Math.floor(theTime) + '秒';
  if (theTime1 > 0) {
    result = '' + Math.floor(theTime1) + '分' + result;
  }
  if (theTime2 > 0) {
    result = '' + Math.floor(theTime2) + '小时' + result;
  }
  return result;
}

/**
 * 
 * @param dataUrl
 * @returns Blob
 */
export function dataUrlToBlob(dataUrl: string) {
  const arr = dataUrl.split(',');
  const mime = (arr[0].match(/:(.*?);/) as any)[1];
  const bstr = atob(arr[1]);
  let n = bstr.length;
  const u8arr = new Uint8Array(n);
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n);
  }
  return new Blob([u8arr], { type: mime });
}

export const releaseCanvas = (canvas: HTMLCanvasElement) => {
  canvas.width = 1;
  canvas.height = 1;
  const ctx = canvas.getContext('2d');
  ctx && ctx.clearRect(0, 0, 1, 1);
}

export const loadingIcon = `<circle class="path" cx="25" cy="25" r="12" fill="none"></circle>`;
